Skip to content

ES6 和 ES5 的写法比较

✍️ w 🕒 2024-06-17 14:53:00(5 days ago) 🔗 A.前端知识整理

ES6 出现了class 语法糖更加方便让 js 可以创建对象

  1. ES5 中类的写法:
javascript
function PersonType(name) {
    this.name = name;
}
PersonType.prototype.sayName = function () {
    console.log(this.name);
};
var personType = new PersonType('wang');
personType.sayName(); // wang

console.log('PersonType instanceof PersonType:', personType instanceof PersonType); // true
console.log('PersonType instanceof Object:', personType instanceof Object); // true
  1. ES6 中类的写法:
javascript
class PersonClass {
    constructor(name) {
        this.name = name;
    }

    sayName() {
        console.log(this.name);
    }
}
let personClass = new PersonClass('wang');
personClass.sayName(); // wang

console.log('PersonClass instanceof PersonClass:', personClass instanceof PersonClass); // true
console.log('PersonClass instanceof Object:', personClass instanceof Object); // true

console.log('typeof PersonClass:', typeof PersonClass); // function

ES6 和 ES5 类的其他不同点

  1. 函数声明提升 vs. 类声明不可提升:

    • 函数声明可以被提升,类声明类似 let 声明,不能被提升。
    • 声明前使用类会导致报错。
  2. 自动严格模式:

    • 类声明的所有代码自动运行在严格模式下。
  3. 方法不可枚举:

    • 在 ES5 中需要手动指定方法不可枚举。
    • ES6 类方法默认不可枚举,挂在对象原型上。
  4. [[Construct]] 方法:

    • 通过 new 调用不含 [[Construct]] 的方法会报错。例如箭头函数
  5. 构造函数必须使用 new 调用:

    • 直接调用类的构造函数会抛出错误。
  6. 类名不可修改:

    • 类声明结束后类名依然可以修改,但在类中修改会报错。
javascript
class Foo {
    constructor() {
        Foo = "bar";  // 这里会抛出错误
    }
}
Foo = "bar"; // 类声明结束后才可以修改类名

代码优化与实现

javascript
// ES5 版本的符合以上特性的类实现

let PersonType2 = (function () {
    "use strict";
    const PersonType2 = function (name) {
        if (typeof new.target === "undefined") {
            throw new Error("Constructor must be called with new.");
        }
        this.name = name;
    };
    Object.defineProperty(PersonType2.prototype, "sayName", {
        value: function () {
            if (typeof new.target !== "undefined") {
                throw new Error("Method cannot be called with new.");
            }
            console.log(this.name);
        },
        enumerable: false,
        writable: true,
        configurable: true
    });
    return PersonType2;
}());

const a = new PersonType2('wang');
console.log(a.name); // wang

访问器属性写法比较

  1. ES5 实现:
javascript
let CustomHTMLElement = (function() {
    "use strict";
    const CustomHTMLElement = function(element) {
        if (typeof new.target === "undefined") {
            throw new Error("Constructor must be called with new.");
        }
        this.element = element;
    }
    Object.defineProperty(CustomHTMLElement.prototype, "html", {
        enumerable: false,
        configurable: true,
        get: function() {
            return this.element.innerHTML;
        },
        set: function(value) {
            this.element.innerHTML = value;
        }
    });
    return CustomHTMLElement;
}());
  1. ES6 类实现:
javascript
class CustomHTMLElement {
    constructor(element) {
        this.element = element;
    }
    get html() {
        return this.element.innerHTML;
    }
    set html(value) {
        this.element.innerHTML = value;
    }
}

var descriptor = Object.getOwnPropertyDescriptor(CustomHTMLElement.prototype, "html");
console.log("get" in descriptor); // true
console.log("set" in descriptor); // true
console.log(descriptor.enumerable); // false

优化建议

  1. 在大型项目中,使用 ES6 类可以提高代码的可读性和可维护性。
  2. 尽量在类的构造函数中定义所有实例属性,避免属性混乱。
  3. 避免在类中直接修改类名,确保代码逻辑清晰。
  4. 使用 Object.defineProperty 管理 ES5 访问器属性,确保代码在未来的 ES6 迁移中更简便。

Released under the MIT License.